﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using MTQ.DAL;
using MTQ.IDAL;
using System.Web;
using MTQ.Common;
using MTQ.Model;
using System.Data;
using System.Configuration;
using System.Data.SqlClient;

namespace MTQ.BLL
{
    public abstract class BaseService<T> where T : class, new()
    {
        /// <summary>
        /// 当前仓储
        /// </summary>
        public IDAL.IBaseRepository<T> CurrentRepository { get; set; }

        /// <summary>
        /// DbSession的存放，为了职责单一的原则，将获取线程内唯一实例的DbSession的逻辑放到工厂里面去了
        /// </summary>
        public IDbSession _DbSession = DbSessionFactory.GetCurrenntDbSession();

        /// <summary>
        /// 基类的构造函数
        /// </summary>
        public BaseService()
        {
            SetCurrentRepository();  //构造函数里面去调用了，此设置当前仓储的抽象方法
        }

        /// <summary>
        /// 子类必须实现
        /// </summary>
        public abstract void SetCurrentRepository();

        /// <summary>
        /// 实现对数据库的添加功能
        /// </summary>
        /// <param name="entity">实体类</param>
        /// <returns>返回实体结果</returns>
        public T AddEntity(T entity)
        {

            //调用T对应的仓储来做添加工作
            var AddEntity = CurrentRepository.AddEntity(entity);
            _DbSession.SaveChanges();
            return AddEntity;
        }

        /// <summary>
        /// 实现对数据库的添加功能
        /// </summary>
        /// <param name="entity">实体类</param>
        /// <returns>返回实体结果</returns>
        public int AddEntityCount(T entity)
        {
            //调用T对应的仓储来做添加工作
            var AddEntity = CurrentRepository.AddEntity(entity);

            return _DbSession.SaveChanges();
        }

        public bool AddListEntity(List<T> listEntity)
        {

            CurrentRepository.AddListEntity(listEntity);
            return _DbSession.SaveChanges() > 0;
        }

        /// <summary>
        /// 实现对数据的修改功能
        /// </summary>
        /// <param name="entity">实体类</param>
        /// <returns>如果执行成功，则返回true，否则返回false</returns>
        public bool UpdateEntity(T entity)
        {
            return CurrentRepository.UpdateEntity(entity);
            //return _DbSession.SaveChanges() > 0;
        }

        /// <summary>
        /// 实现对数据库的修改功能
        /// </summary>
        /// <returns>返回受影响的行数</returns>
        public int UpdateEntity()
        {
            return _DbSession.SaveChanges();
        }

        /// <summary>
        /// 实现对数据库的删除功能
        /// </summary>
        /// <param name="entity">实体类</param>
        /// <returns>如果执行成功，则返回true，否则返回false</returns>
        public bool DeleteEntity(T entity)
        {
            CurrentRepository.DeleteEntity(entity);
            return _DbSession.SaveChanges() > 0;
        }
        public bool DeleteListEntity(List<T> listEntity)
        {

            CurrentRepository.DeleteListEntity(listEntity);
            return _DbSession.SaveChanges() > 0;
        }

        /// <summary>
        /// 实现对数据库的查询  --简单查询
        /// </summary>
        /// <param name="whereLambda">查询条件</param>
        /// <returns>返回实体类的IQueryable集合</returns>
        public IQueryable<T> LoadEntities(Expression<Func<T, bool>> whereLambda)
        {
            return CurrentRepository.LoadEntities(whereLambda);
        }


        /// <summary>
        /// 实现对数据的分页查询
        /// </summary>
        /// <typeparam name="S">按照某个类进行排序</typeparam>
        /// <param name="pageIndex">当前第几页</param>
        /// <param name="pageSize">一页显示多少条数据</param>
        /// <param name="total">总条数</param>
        /// <param name="whereLambda">取得排序的条件</param>
        /// <param name="isAsc">如何排序，根据倒叙还是升序</param>
        /// <param name="orderByLambda">根据那个字段进行排序</param>
        /// <returns>返回实体类的IQueryable集合</returns>
        public IQueryable<T> LoadPageEntities<S>(int pageIndex, int pageSize, out int total, Expression<Func<T, bool>> whereLambda,
                                           bool isAsc, Expression<Func<T, S>> orderByLambda)
        {
            return CurrentRepository.LoadPageEntities(pageIndex, pageSize, out total, whereLambda, isAsc, orderByLambda);
        }

        public int SaveChange()
        {
            return _DbSession.SaveChanges();
        }

        protected virtual IQueryable<T> GetBootstrapQueryable<K>(K paramterquery) where K : ParamterQuery
        {
            return null;
        }

        public ServertBootStrapTable LoadBootstrapSearchData(ParamterQuery paramterquery, HttpRequestBase Request)
        {
            ServertBootStrapTable servertBootStrapTable = new ServertBootStrapTable();
            try
            {
                int limit = int.Parse(Request["limit"]);
                //int limit = 100;
                string order = Request["order"];
                string sort = Request["sort"];
                int offset = int.Parse(Request["offset"]);


                paramterquery.PageSize = limit;
                paramterquery.Order = order;
                paramterquery.Sort = sort;
                paramterquery.Offset = offset;

                paramterquery.PageIndex = offset / limit + 1;


                IQueryable<T> iqueryableT = this.GetBootstrapQueryable(paramterquery);

                paramterquery.Total = iqueryableT.Count();

                #region 排序
                {
                    var param = Expression.Parameter(typeof(T), "x");
                    Expression expr = Expression.Property(param, paramterquery.Sort);



                    //排序
                    string exprType = expr.Type.ToString();
                    if (order == "desc")
                    {
                        switch (exprType)
                        {

                            case "System.Guid":
                                iqueryableT = iqueryableT.OrderByDescending(ExpressionLambda.GetSortExpression<T, Guid>(paramterquery.Sort)); break;
                            case "System.Nullable`1[System.DateTime]":
                                iqueryableT = iqueryableT.OrderByDescending(ExpressionLambda.GetSortExpression<T, Nullable<DateTime>>(paramterquery.Sort)); break;
                            //james Add 7/27
                            case "System.Nullable`1[System.Boolean]":
                                iqueryableT = iqueryableT.OrderByDescending(ExpressionLambda.GetSortExpression<T, Nullable<Boolean>>(paramterquery.Sort)); break;
                            //
                            case "System.Int32":
                                iqueryableT = iqueryableT.OrderByDescending(ExpressionLambda.GetSortExpression<T, Int32>(paramterquery.Sort));
                                break;
                            case "System.Nullable`1[System.TimeSpan]":
                                iqueryableT = iqueryableT.OrderByDescending(ExpressionLambda.GetSortExpression<T, Nullable<System.TimeSpan>>(paramterquery.Sort));
                                break;
                            case "System.DateTime":
                                iqueryableT = iqueryableT.OrderByDescending(ExpressionLambda.GetSortExpression<T, DateTime>(paramterquery.Sort));
                                break;
                            default:
                                iqueryableT = iqueryableT.OrderByDescending(ExpressionLambda.GetSortExpression<T, object>(paramterquery.Sort)); break;


                        }
                    }
                    else
                    {
                        switch (exprType)
                        {

                            case "System.Guid":
                                iqueryableT = iqueryableT.OrderBy(ExpressionLambda.GetSortExpression<T, Guid>(paramterquery.Sort)); break;
                            case "System.Nullable`1[System.DateTime]":
                                iqueryableT = iqueryableT.OrderBy(ExpressionLambda.GetSortExpression<T, Nullable<DateTime>>(paramterquery.Sort)); break;
                            //james Add 7/27
                            case "System.Nullable`1[System.Boolean]":
                                iqueryableT = iqueryableT.OrderBy(ExpressionLambda.GetSortExpression<T, Nullable<Boolean>>(paramterquery.Sort)); break;
                            //
                            case "System.Int32":
                                iqueryableT = iqueryableT.OrderBy(ExpressionLambda.GetSortExpression<T, Int32>(paramterquery.Sort));
                                break;
                            case "System.Nullable`1[System.TimeSpan]":
                                iqueryableT = iqueryableT.OrderBy(ExpressionLambda.GetSortExpression<T, Nullable<System.TimeSpan>>(paramterquery.Sort));
                                break;
                            case "System.DateTime":
                                iqueryableT = iqueryableT.OrderBy(ExpressionLambda.GetSortExpression<T, DateTime>(paramterquery.Sort));
                                break;

                            default:
                                iqueryableT = iqueryableT.OrderBy(ExpressionLambda.GetSortExpression<T, object>(paramterquery.Sort)); break;
                        }

                    }


                }

                #endregion
                //分页
                iqueryableT = iqueryableT.Skip(paramterquery.PageSize * (paramterquery.PageIndex - 1)).Take(paramterquery.PageSize);


                List<T> lstTrialHeader = iqueryableT.ToList();


                servertBootStrapTable.total = paramterquery.Total;
                servertBootStrapTable.rows = lstTrialHeader;
                return servertBootStrapTable;
            }
            catch (Exception e)
            {
                servertBootStrapTable.total = 0;
                servertBootStrapTable.rows = null;
                return servertBootStrapTable;
            }

        }

        public static DataSet GetDataPage(string tableName, int _pagerIndex, int _pagerSize, string WhereString, string _orderString)
        {
            string sqlConnect = ConfigurationManager.ConnectionStrings["MTQFramework"].ToString();
            DataSet dt = SqlHelperPage.GetDataPage(sqlConnect, "*", tableName, _pagerIndex, _pagerSize, WhereString, _orderString);
            return dt;
        }

        public static DataSet GetDataNoPage(string tableName, string WhereString, string _orderString)
        {
            string sqlConnect = ConfigurationManager.ConnectionStrings["MTQFramework"].ToString();
            DataSet dt = SqlHelperPage.GetDataNoPage(sqlConnect, "*", tableName, WhereString, _orderString);
            return dt;
        }



        public ServertLayuiTable<T> LoadLayuiSearchData(ParamterQuery paramterquery, HttpRequestBase Request)
        {
            ServertLayuiTable<T> servertLayuiTable = new ServertLayuiTable<T>();
            try
            {
                int limit = int.Parse(Request["limit"]);
                //int limit = 100;
                string order = Request["sortType"];
                string sort = Request["sortField"];
                int pageIndex = int.Parse(Request["page"]);


                paramterquery.PageSize = limit;
                paramterquery.Order = order;
                paramterquery.Sort = sort;
               // paramterquery.Offset = offset;

                paramterquery.PageIndex = pageIndex;


                IQueryable<T> iqueryableT = this.GetBootstrapQueryable(paramterquery);

                paramterquery.Total = iqueryableT.Count();

                #region 排序
                if (paramterquery.Sort != null)
                {
                    var param = Expression.Parameter(typeof(T), "x");
                    Expression expr = Expression.Property(param, paramterquery.Sort);
                    //排序
                    string exprType = expr.Type.ToString();
                    if (order == "desc")
                    {
                        switch (exprType)
                        {

                            case "System.Guid":
                                iqueryableT = iqueryableT.OrderByDescending(ExpressionLambda.GetSortExpression<T, Guid>(paramterquery.Sort)); break;
                            case "System.Nullable`1[System.DateTime]":
                                iqueryableT = iqueryableT.OrderByDescending(ExpressionLambda.GetSortExpression<T, Nullable<DateTime>>(paramterquery.Sort)); break;
                            //james Add 7/27
                            case "System.Nullable`1[System.Boolean]":
                                iqueryableT = iqueryableT.OrderByDescending(ExpressionLambda.GetSortExpression<T, Nullable<Boolean>>(paramterquery.Sort)); break;
                            //
                            case "System.Int32":
                                iqueryableT = iqueryableT.OrderByDescending(ExpressionLambda.GetSortExpression<T, Int32>(paramterquery.Sort));
                                break;
                            case "System.Nullable`1[System.TimeSpan]":
                                iqueryableT = iqueryableT.OrderByDescending(ExpressionLambda.GetSortExpression<T, Nullable<System.TimeSpan>>(paramterquery.Sort));
                                break;
                            case "System.DateTime":
                                iqueryableT = iqueryableT.OrderByDescending(ExpressionLambda.GetSortExpression<T, DateTime>(paramterquery.Sort));
                                break;
                            default:
                                iqueryableT = iqueryableT.OrderByDescending(ExpressionLambda.GetSortExpression<T, object>(paramterquery.Sort)); break;


                        }
                    }
                    else
                    {
                        switch (exprType)
                        {

                            case "System.Guid":
                                iqueryableT = iqueryableT.OrderBy(ExpressionLambda.GetSortExpression<T, Guid>(paramterquery.Sort)); break;
                            case "System.Nullable`1[System.DateTime]":
                                iqueryableT = iqueryableT.OrderBy(ExpressionLambda.GetSortExpression<T, Nullable<DateTime>>(paramterquery.Sort)); break;
                            //james Add 7/27
                            case "System.Nullable`1[System.Boolean]":
                                iqueryableT = iqueryableT.OrderBy(ExpressionLambda.GetSortExpression<T, Nullable<Boolean>>(paramterquery.Sort)); break;
                            //
                            case "System.Int32":
                                iqueryableT = iqueryableT.OrderBy(ExpressionLambda.GetSortExpression<T, Int32>(paramterquery.Sort));
                                break;
                            case "System.Nullable`1[System.TimeSpan]":
                                iqueryableT = iqueryableT.OrderBy(ExpressionLambda.GetSortExpression<T, Nullable<System.TimeSpan>>(paramterquery.Sort));
                                break;
                            case "System.DateTime":
                                iqueryableT = iqueryableT.OrderBy(ExpressionLambda.GetSortExpression<T, DateTime>(paramterquery.Sort));
                                break;

                            default:
                                iqueryableT = iqueryableT.OrderBy(ExpressionLambda.GetSortExpression<T, object>(paramterquery.Sort)); break;
                        }
                    }

                }
                else
                {
                    //var  s = ExpressionLambda.GetSortExpression<T, object>(TableKey());

                    iqueryableT=BootstrapQueryableOrderby<T>(iqueryableT);
                }

                #endregion
                //分页
                iqueryableT = iqueryableT.Skip(paramterquery.PageSize * (paramterquery.PageIndex - 1)).Take(paramterquery.PageSize);


                List<T> lstTrialHeader = iqueryableT.ToList();


                servertLayuiTable.count = paramterquery.Total;
                servertLayuiTable.data = lstTrialHeader;
                return servertLayuiTable;
            }
            catch (Exception e)
            {
                servertLayuiTable.count = 0;
                servertLayuiTable.data = null;
                return servertLayuiTable;
            }

        }

        /// <summary>
        /// 分页传 4个值paramterquery.PageSize 每页大小 ；paramterquery.PageIndex页标 ；paramterquery.Order排序方向asc/desc；paramterquery.Sort 排序字段 
        /// </summary>
        /// <param name="paramterquery"></param>
        /// <returns></returns>
        public ServertLayuiTable<T> LoadApiSearchData(ParamterQuery paramterquery)
        {
            ServertLayuiTable<T> servertLayuiTable = new ServertLayuiTable<T>();
            try
            {
                //int limit = int.Parse(Request["limit"]);
                ////int limit = 100;
                //string order = Request["sortType"];
                //string sort = Request["sortField"];
                //int pageIndex = int.Parse(Request["page"]);

                //paramterquery.PageSize = limit;
                //paramterquery.Order = order;
                //paramterquery.Sort = sort;
                //// paramterquery.Offset = offset;
                //paramterquery.PageIndex = pageIndex;


                IQueryable<T> iqueryableT = this.GetBootstrapQueryable(paramterquery);

                paramterquery.Total = iqueryableT.Count();

                #region 排序
                if (paramterquery.Sort != null)
                {
                    var param = Expression.Parameter(typeof(T), "x");
                    Expression expr = Expression.Property(param, paramterquery.Sort);
                    //排序
                    string exprType = expr.Type.ToString();
                    if (paramterquery.Order == "desc")
                    {
                        switch (exprType)
                        {

                            case "System.Guid":
                                iqueryableT = iqueryableT.OrderByDescending(ExpressionLambda.GetSortExpression<T, Guid>(paramterquery.Sort)); break;
                            case "System.Nullable`1[System.DateTime]":
                                iqueryableT = iqueryableT.OrderByDescending(ExpressionLambda.GetSortExpression<T, Nullable<DateTime>>(paramterquery.Sort)); break;
                            //james Add 7/27
                            case "System.Nullable`1[System.Boolean]":
                                iqueryableT = iqueryableT.OrderByDescending(ExpressionLambda.GetSortExpression<T, Nullable<Boolean>>(paramterquery.Sort)); break;
                            //
                            case "System.Int32":
                                iqueryableT = iqueryableT.OrderByDescending(ExpressionLambda.GetSortExpression<T, Int32>(paramterquery.Sort));
                                break;
                            case "System.Nullable`1[System.TimeSpan]":
                                iqueryableT = iqueryableT.OrderByDescending(ExpressionLambda.GetSortExpression<T, Nullable<System.TimeSpan>>(paramterquery.Sort));
                                break;
                            case "System.DateTime":
                                iqueryableT = iqueryableT.OrderByDescending(ExpressionLambda.GetSortExpression<T, DateTime>(paramterquery.Sort));
                                break;
                            default:
                                iqueryableT = iqueryableT.OrderByDescending(ExpressionLambda.GetSortExpression<T, object>(paramterquery.Sort)); break;


                        }
                    }
                    else
                    {
                        switch (exprType)
                        {

                            case "System.Guid":
                                iqueryableT = iqueryableT.OrderBy(ExpressionLambda.GetSortExpression<T, Guid>(paramterquery.Sort)); break;
                            case "System.Nullable`1[System.DateTime]":
                                iqueryableT = iqueryableT.OrderBy(ExpressionLambda.GetSortExpression<T, Nullable<DateTime>>(paramterquery.Sort)); break;
                            //james Add 7/27
                            case "System.Nullable`1[System.Boolean]":
                                iqueryableT = iqueryableT.OrderBy(ExpressionLambda.GetSortExpression<T, Nullable<Boolean>>(paramterquery.Sort)); break;
                            //
                            case "System.Int32":
                                iqueryableT = iqueryableT.OrderBy(ExpressionLambda.GetSortExpression<T, Int32>(paramterquery.Sort));
                                break;
                            case "System.Nullable`1[System.TimeSpan]":
                                iqueryableT = iqueryableT.OrderBy(ExpressionLambda.GetSortExpression<T, Nullable<System.TimeSpan>>(paramterquery.Sort));
                                break;
                            case "System.DateTime":
                                iqueryableT = iqueryableT.OrderBy(ExpressionLambda.GetSortExpression<T, DateTime>(paramterquery.Sort));
                                break;

                            default:
                                iqueryableT = iqueryableT.OrderBy(ExpressionLambda.GetSortExpression<T, object>(paramterquery.Sort)); break;
                        }
                    }

                }
                else
                {
                    //var  s = ExpressionLambda.GetSortExpression<T, object>(TableKey());

                    iqueryableT = BootstrapQueryableOrderby<T>(iqueryableT);
                }

                #endregion
                //分页
                iqueryableT = iqueryableT.Skip(paramterquery.PageSize * (paramterquery.PageIndex - 1)).Take(paramterquery.PageSize);


                List<T> lstTrialHeader = iqueryableT.ToList();


                servertLayuiTable.count = paramterquery.Total;
                servertLayuiTable.data = lstTrialHeader;
                return servertLayuiTable;
            }
            catch (Exception e)
            {
                servertLayuiTable.count = 0;
                servertLayuiTable.data = null;
                return servertLayuiTable;
            }

        }


        protected virtual IQueryable<T> BootstrapQueryableOrderby<K>(IQueryable<T> paramterquery)
        {
            return paramterquery;
        }


        public virtual IQueryable<T> GetIQueryable<K>(K paramterquery) where K : ParamterQuery
        {
            return this.GetBootstrapQueryable<ParamterQuery>(paramterquery); 
        }

        public static DataSet GetDataPage(string tableName, int _pagerIndex, int _pagerSize, string WhereString, string _orderString, params SqlParameter[] commandParameters)
        {
            string sqlConnect = ConfigurationManager.ConnectionStrings["MTQFramework"].ToString();
            DataSet dt = SqlHelperPage.GetDataPage(sqlConnect, "*", tableName, _pagerIndex, _pagerSize, WhereString, _orderString, commandParameters);
            return dt;
        }
        public static DataSet GetDataNoPage(string tableName, string WhereString, string _orderString, params SqlParameter[] commandParameters)
        {
            string sqlConnect = ConfigurationManager.ConnectionStrings["MTQFramework"].ToString();
            DataSet dt = SqlHelperPage.GetDataNoPage(sqlConnect, "*", tableName, WhereString, _orderString, commandParameters);
            return dt;
        }

        public static bool DateTableSave(DataTable dt, string tablename)
        {
            return DAL.SqlBulkHelper.Save(dt, tablename);
        }

    }
}
